package org.jeecg.common.util.pay;

import cn.hutool.core.util.XmlUtil;
import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.*;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.AesException;
import org.jeecg.common.system.vo.JwidModel;
import org.jeecg.common.system.vo.WeChatPayModel;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;

@Component
public class WXPayUtils {

    private CloseableHttpClient httpClient;
    private CloseableHttpClient httpClient1;
    private CloseableHttpClient httpClient8;

    private static final String MODEL = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    public void setup(WeChatPayModel payModel) throws UnsupportedEncodingException {

        // 加载商户私钥
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(payModel.getMchPrivateKeyStr());

        //System.out.println(payModel.getWeixinMchid());
        //System.out.println(payModel.getMchSerialNo());
        //System.out.println(payModel.getWeixinMchkey());
        // 加载平台证书（mchId：商户号,mchSerialNo：商户证书序列号,apiV3Key：V3密钥）
        AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
                new WechatPay2Credentials(payModel.getWeixinMchid()
                        , new PrivateKeySigner(payModel.getMchSerialNo(), merchantPrivateKey))
                ,payModel.getWeixinMchkey().getBytes("utf-8"));

        //// 加载平台证书（mchId：商户号,mchSerialNo：商户证书序列号,apiV3Key：V3秘钥）
        //AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
        //        new WechatPay2Credentials(payModel.getWeixinMchid()
        //                , new PrivateKeySigner(payModel.getMchSerialNo()
        //                , merchantPrivateKey))
        //        , payModel.getWeixinMchkey().getBytes("utf-8"));

        // 初始化httpClient
        httpClient = WechatPayHttpClientBuilder.create()
                .withMerchant(payModel.getWeixinMchid(), payModel.getMchSerialNo(), merchantPrivateKey)
                .withValidator(new WechatPay2Validator(verifier)).build();


        //PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(privateKey);
        //X509Certificate wechatPayCertificate = PemUtil.loadCertificate(
        //        new ByteArrayInputStream(certificate.getBytes(StandardCharsets.UTF_8)));
        //
        //ArrayList<X509Certificate> listCertificates = new ArrayList<>();
        //listCertificates.add(wechatPayCertificate);
        //
        //WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
        //        .withMerchant(mchId, mchSerialNo, PemUtil.loadPrivateKey(privateKey))
        //        .withWechatPay(listCertificates);
        //httpClient = builder.build();

        //X509Certificate wechatPayCertificate = PemUtil.loadCertificate(
        //        new ByteArrayInputStream(payModel.getWeixinCertificates().getBytes(StandardCharsets.UTF_8)));
        //
        //ArrayList<X509Certificate> listCertificates = new ArrayList<>();
        //listCertificates.add(wechatPayCertificate);
        //
        //httpClient= WechatPayHttpClientBuilder.create()
        //        .withMerchant(payModel.getWeixinMchid(), payModel.getWeixinSerialNumber()
        //                , merchantPrivateKey)
        //        .withWechatPay(listCertificates).build();
    }
    public void setup8(WeChatPayModel payModel) throws UnsupportedEncodingException {

        // 加载商户私钥
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(payModel.getMchPrivateKeyStr());

        // 加载平台证书（mchId：商户号,mchSerialNo：商户证书序列号,apiV3Key：V3密钥）
        AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
                new WechatPay2Credentials(payModel.getWeixinMchid()
                        , new PrivateKeySigner(payModel.getMchSerialNo(), merchantPrivateKey))
                ,payModel.getWeixinMchkey().getBytes("utf-8"));


        // 初始化httpClient
        httpClient8 = WechatPayHttpClientBuilder.create()
                .withMerchant(payModel.getWeixinMchid(), payModel.getMchSerialNo(), merchantPrivateKey)
                .withValidator(new WechatPay2Validator(verifier)).build();
    }
    public void setup1(WeChatPayModel payModel) throws UnsupportedEncodingException {

        // 加载商户私钥
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(payModel.getMchPrivateKeyStr());

        // 加载平台证书（mchId：商户号,mchSerialNo：商户证书序列号,apiV3Key：V3密钥）
        AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
                new WechatPay2Credentials(payModel.getWeixinMchid()
                        , new PrivateKeySigner(payModel.getMchSerialNo(), merchantPrivateKey))
                ,payModel.getWeixinMchkey().getBytes("utf-8"));


        // 初始化httpClient
        httpClient1 = WechatPayHttpClientBuilder.create()
                .withMerchant(payModel.getWeixinMchid(), payModel.getMchSerialNo(), merchantPrivateKey)
                .withValidator(new WechatPay2Validator(verifier)).build();
    }

    /*回调通知*/
    public boolean verifySigna(JwidModel payModel, String serialNo, String signStr, String signature) throws Exception {
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(payModel.getMchkeyPath());
        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        // 向证书管理器增加需要自动更新平台证书的商户信息
        certificatesManager.putMerchant(payModel.getWeixinMchid()
                ,new WechatPay2Credentials(payModel.getWeixinMchid()
                    ,new PrivateKeySigner(payModel.getMchSerialNo()
                    , merchantPrivateKey))
                , payModel.getWeixinMchkey().getBytes(StandardCharsets.UTF_8));
        // 从证书管理器中获取verifier
        Verifier verifier = certificatesManager.getVerifier(payModel.getWeixinMchid());
       return verifier.verify(serialNo, signStr.getBytes("utf-8"), signature);
    }

    /**
     * wxMchid商户号
     * wxCertno证书编号
     * wxCertPath证书地址
     * wxPaternerKey   v3秘钥
     * url jsapi下单地址
     * body 构造好的消息体
     */
    public JSONObject doPostWexinV3(WeChatPayModel payModel,String url, String body) throws UnsupportedEncodingException {

        if(payModel.getTenantId() ==8){
            if (httpClient8 == null) {
                setup8(payModel);
            }
        }else  if(payModel.getTenantId() ==16) {
            if (httpClient == null) {
                setup(payModel);
            }
        }else  if(payModel.getTenantId() ==1) {
            if (httpClient1 == null) {
                setup1(payModel);
            }
        }


        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type", "application/json;chartset=utf-8");
        httpPost.addHeader("Accept", "application/json");
        try {
            if (body == null) {
                throw new IllegalArgumentException("data参数不能为空");
            }
            StringEntity stringEntity = new StringEntity(body, "utf-8");
            httpPost.setEntity(stringEntity);
            // 直接执行execute方法，官方会自动处理签名和验签，并进行证书自动更新

            HttpResponse httpResponse =null;
            if(payModel.getTenantId() ==8){
                httpResponse=httpClient8.execute(httpPost);

            }else  if(payModel.getTenantId() ==16) {
                httpResponse=httpClient.execute(httpPost);
            }else  if(payModel.getTenantId() ==1) {
                httpResponse=httpClient1.execute(httpPost);
            }
            HttpEntity httpEntity = httpResponse.getEntity();

            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                String jsonResult = EntityUtils.toString(httpEntity);
                System.out.println(jsonResult);
                return JSONObject.parseObject(jsonResult);
            } else {
                System.err.println("微信支付错误信息" + EntityUtils.toString(httpEntity));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 预付订单状态查询
     * @param jwidModel
     * @param prepayId
     * @throws Exception
     */
    public Result<?> queryPreOrder(JwidModel jwidModel, String prepayId) throws Exception {
        if(prepayId.length()>32){
            prepayId= prepayId.substring(0,32);
        }
        //请求URL
        URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/transactions/id/"+prepayId);
        uriBuilder.setParameter("mchid", jwidModel.getWeixinMchid());

        WeChatPayModel payModel = new WeChatPayModel();
        payModel.setAccessToken(jwidModel.getAccessToken());
        payModel.setJwid(jwidModel.getJwid());
        payModel.setToken(jwidModel.getToken());
        payModel.setWeixinAppid(jwidModel.getWeixinAppid());
        payModel.setWeixinMchid(jwidModel.getWeixinMchid());
        payModel.setWeixinMchkey(jwidModel.getWeixinMchkey());
        payModel.setMchSerialNo(jwidModel.getMchSerialNo());
        //payModel.setWeixinAppsecret(jwidModel.getWeixinAppsecret());
        payModel.setMchPrivateKeyStr(jwidModel.getMchkeyPath());

        if(payModel.getTenantId() ==8){
            if (httpClient8 == null) {
                setup8(payModel);
            }
        }else  if(payModel.getTenantId() ==16) {
            if (httpClient == null) {
                setup(payModel);
            }
        }else  if(payModel.getTenantId() ==1) {
            if (httpClient1 == null) {
                setup1(payModel);
            }
        }

        //完成签名并执行请求
        HttpGet httpGet = new HttpGet(uriBuilder.build());
        httpGet.addHeader("Accept", "application/json");
        CloseableHttpResponse response =null;
        if(payModel.getTenantId() ==8){
            response =  httpClient8.execute(httpGet);

        }else  if(payModel.getTenantId() ==16) {
            response = httpClient.execute(httpGet);
        }else  if(payModel.getTenantId() ==1) {
            response = httpClient1.execute(httpGet);
        }

        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
                return Result.OK(EntityUtils.toString(response.getEntity()));
            } else if (statusCode == 204) {
                System.out.println("success");
                return Result.OK(EntityUtils.toString(response.getEntity()));
            } else {
                System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
                return Result.error("支付未成功：",EntityUtils.toString(response.getEntity()));
            }
        } finally {
            response.close();
        }

    }
    /**
     * 预付订单状态查询
     * @param jwidModel
     * @param orderNo
     * @throws Exception
     */
    public Result<?> queryPreOrderNo(JwidModel jwidModel, String orderNo) throws Exception {

        //请求URL
        URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/"+orderNo);
        uriBuilder.setParameter("mchid", jwidModel.getWeixinMchid());

        WeChatPayModel payModel = new WeChatPayModel();
        payModel.setAccessToken(jwidModel.getAccessToken());
        payModel.setJwid(jwidModel.getJwid());
        payModel.setToken(jwidModel.getToken());
        payModel.setWeixinAppid(jwidModel.getWeixinAppid());
        payModel.setWeixinMchid(jwidModel.getWeixinMchid());
        payModel.setWeixinMchkey(jwidModel.getWeixinMchkey());
        payModel.setMchSerialNo(jwidModel.getMchSerialNo());
        //payModel.setWeixinAppsecret(jwidModel.getWeixinAppsecret());
        payModel.setMchPrivateKeyStr(jwidModel.getMchkeyPath());
        payModel.setTenantId(jwidModel.getTenantId());

        if(payModel.getTenantId() ==8){
            if (httpClient8 == null) {
                setup8(payModel);
            }
        }else  if(payModel.getTenantId() ==16) {
            if (httpClient == null) {
                setup(payModel);
            }
        }else  if(payModel.getTenantId() ==1) {
            if (httpClient1 == null) {
                setup1(payModel);
            }
        }
        //完成签名并执行请求
        HttpGet httpGet = new HttpGet(uriBuilder.build());
        httpGet.addHeader("Accept", "application/json");

        CloseableHttpResponse response =null;
        if(payModel.getTenantId() ==8){
            response =  httpClient8.execute(httpGet);

        }else  if(payModel.getTenantId() ==16) {
            response = httpClient.execute(httpGet);
        }else  if(payModel.getTenantId() ==1) {
            response = httpClient1.execute(httpGet);
        }

        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
                return Result.OK(EntityUtils.toString(response.getEntity()));
            } else if (statusCode == 204) {
                System.out.println("success");
                return Result.OK(EntityUtils.toString(response.getEntity()));
            } else {
                System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
                return Result.error("支付未成功：",EntityUtils.toString(response.getEntity()));
            }
        } finally {
            response.close();
        }

    }

    /**
     * 预付订单状态查询-根据交易号
     * @param jwidModel
     * @param transactionId
     * @throws Exception
     */
    public Result<?> queryWxtOrderNo(JwidModel jwidModel, String transactionId) throws Exception {

        //请求URL
        URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/transactions/id/"+transactionId);
        uriBuilder.setParameter("mchid", jwidModel.getWeixinMchid());

        WeChatPayModel payModel = new WeChatPayModel();
        payModel.setAccessToken(jwidModel.getAccessToken());
        payModel.setJwid(jwidModel.getJwid());
        payModel.setToken(jwidModel.getToken());
        payModel.setWeixinAppid(jwidModel.getWeixinAppid());
        payModel.setWeixinMchid(jwidModel.getWeixinMchid());
        payModel.setWeixinMchkey(jwidModel.getWeixinMchkey());
        payModel.setMchSerialNo(jwidModel.getMchSerialNo());
        //payModel.setWeixinAppsecret(jwidModel.getWeixinAppsecret());
        payModel.setMchPrivateKeyStr(jwidModel.getMchkeyPath());
        payModel.setTenantId(jwidModel.getTenantId());

        if(payModel.getTenantId() ==8){
            if (httpClient8 == null) {
                setup8(payModel);
            }
        }else  if(payModel.getTenantId() ==16) {
            if (httpClient == null) {
                setup(payModel);
            }
        }else  if(payModel.getTenantId() ==1) {
            if (httpClient1 == null) {
                setup1(payModel);
            }
        }
        //完成签名并执行请求
        HttpGet httpGet = new HttpGet(uriBuilder.build());
        httpGet.addHeader("Accept", "application/json");

        CloseableHttpResponse response =null;
        if(payModel.getTenantId() ==8){
            response =  httpClient8.execute(httpGet);

        }else  if(payModel.getTenantId() ==16) {
            response = httpClient.execute(httpGet);
        }else  if(payModel.getTenantId() ==1) {
            response = httpClient1.execute(httpGet);
        }

        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
                return Result.OK(EntityUtils.toString(response.getEntity()));
            } else if (statusCode == 204) {
                System.out.println("success");
                return Result.OK(EntityUtils.toString(response.getEntity()));
            } else {
                System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
                return Result.error("支付未成功：",EntityUtils.toString(response.getEntity()));
            }
        } finally {
            response.close();
        }

    }


    public void testPay() throws UnsupportedEncodingException {
        JSONObject jsonObject = buildWxJsApiPayJson("你的公众平台小程序等appid", "商户id", "测试商品描述",
                "20220304215501111", "https://www.baidu.com", "2",
                "用户在你的公众平台下的唯一标识，登录后能获取");
        WeChatPayModel payModel=new WeChatPayModel();
        JSONObject jsonObject1 = doPostWexinV3(payModel,"https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi", jsonObject.toJSONString());
        System.out.println(jsonObject1.toJSONString());
    }

    /**
     * 构造微信JsApi付款的json
     * @param appid
     * @param mchid
     * @param description
     * @param out_trade_no
     * @param notify_url
     * @param amount
     * @return
     */
    public JSONObject buildWxJsApiPayJson(String appid , String mchid
            ,String description ,String out_trade_no ,String notify_url
            ,String amount,String openId){

        //订单金额json
        JSONObject amountJson = new JSONObject();
        amountJson.put("total",Integer.valueOf(amount));
        amountJson.put("currency","CNY");

        //支付者json
        JSONObject payerJson = new JSONObject();
        payerJson.put("openid",openId);

        //基础信息json
        JSONObject json = new JSONObject();
        json.put("appid",appid);
        json.put("mchid",mchid);
        json.put("description",description);
        json.put("out_trade_no",out_trade_no);
        json.put("notify_url",notify_url);
        json.put("amount",amountJson);
        json.put("payer",payerJson);
        return json;
    }

    ////回调通知
    //public void notificationHandlerTest() throws Exception {
    //    // 构建request，传入必要参数
    //    NotificationRequest request = new NotificationRequest.Builder().withSerialNumber(wechatPaySerial)
    //            .withNonce(nonce)
    //            .withTimestamp(timestamp)
    //            .withSignature(signature)
    //            .withBody(body)
    //            .build();
    //    NotificationHandler handler = new NotificationHandler(verifier, apiV3Key.getBytes(StandardCharsets.UTF_8));
    //    // 验签和解析请求体
    //    Notification notification = handler.parse(request);
    //
    //    System.out.println(notification.toString());
    //}

    //回调验证
    public String shareTestCallBack(HttpServletRequest request, HttpServletResponse response) throws AesException, IOException {

        String msgSignature = request.getParameter("signature");
        String msgTimestamp = request.getParameter("timestamp");
        String msgNonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");
        //验证签名
        if (verifyUrl(msgSignature, msgTimestamp, msgNonce)) {
            return echostr;
        }

        Map<String, Object> retMap = new HashMap<>(2);
        //boolean flag = WeChatPayParam.checkSign(returnInfo, wechatParameter);
        //if (flag) {
        //    String returnCode = returnInfo.get("return_code").toString();
        //    weChatRechargeService.returnInfo(returnCode, outTradeNo, returnInfo);
            retMap.put("return_code", "SUCCESS");
            retMap.put("return_msg", "OK");
        //} else {
        //    log.error("[验签失败][IP:{}][请求参数:{}][weChatParameter:{}]", IpUtil.getClientIp(request), retInfo, wechatParameter);
        //    retMap.put("return_code", "FAIL");
        //    retMap.put("return_msg", "sign error");
        //}
        //返回给微信通知
        PrintWriter writer = response.getWriter();
        writer.write(XmlUtil.mapToXmlStr(retMap, "xml"));
        writer.flush();
        writer.close();


        return "OK";
    }


    /**
     * 验证Token
     * @param msgSignature 签名串，对应URL参数的signature
     * @param timeStamp 时间戳，对应URL参数的timestamp
     * @param nonce 随机串，对应URL参数的nonce
     *
     * @return 是否为安全签名
     * @throws AesException 执行失败，请查看该异常的错误码和具体的错误信息
     */
    public static boolean verifyUrl(String msgSignature, String timeStamp, String nonce)
            throws AesException {
        // 这里的 WXPublicConstants.TOKEN 填写你自己设置的Token就可以了
        String signature = getSHA1("ysmws", timeStamp, nonce);
        if (!signature.equals(msgSignature)) {
            throw new AesException(AesException.ValidateSignatureError);
        }
        return true;
    }
    /**
     * 用SHA1算法验证Token
     *
     * @param token     票据
     * @param timestamp 时间戳
     * @param nonce     随机字符串
     * @return 安全签名
     * @throws AesException
     */
    public static String getSHA1(String token, String timestamp, String nonce) throws AesException {
        try {
            String[] array = new String[]{token, timestamp, nonce};
            StringBuffer sb = new StringBuffer();
            // 字符串排序
            Arrays.sort(array);
            Arrays.sort(array);
            for (int i = 0; i < 3; i++) {
                sb.append(array[i]);
            }
            String str = sb.toString();
            // SHA1签名生成
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(str.getBytes());
            byte[] digest = md.digest();

            StringBuffer hexstr = new StringBuffer();
            String shaHex = "";
            for (int i = 0; i < digest.length; i++) {
                shaHex = Integer.toHexString(digest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexstr.append(0);
                }
                hexstr.append(shaHex);
            }
            return hexstr.toString();
        } catch (Exception e) {
            e.printStackTrace();
            throw new AesException(AesException.ComputeSignatureError);
        }
    }

    /**
     * 获取私钥。
     *
     * @param filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    public  PrivateKey getPrivateKey(String filename) throws IOException {

        String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");

            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }

    public  String buildSignMessage(ArrayList<String> signMessage) {
        if (signMessage == null || signMessage.size() <= 0) {
            return null;
        }
        StringBuilder sbf = new StringBuilder();
        for (String str : signMessage) {
            sbf.append(str).append("\n");
        }
        return sbf.toString();
    }

    /**
     * 生成签名
     *
     * @param message   请求体
     * @return 生成base64位签名信息
     * @throws Exception
     */
    public String sign(byte[] message, String  yourPrivateKey) {
        try {
            PrivateKey mchPrivateKey = PemUtil.loadPrivateKey(yourPrivateKey);

            // 签名方式（固定SHA256withRSA）
            Signature sign = Signature.getInstance("SHA256withRSA");
            // 使用私钥进行初始化签名（私钥需要从私钥文件【证书】中读取）
            sign.initSign(mchPrivateKey);
            // 签名更新
            sign.update(message);
            // 对签名结果进行Base64编码
            return Base64.getEncoder().encodeToString(sign.sign());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密body的密文
     *
     * "resource": {
     *         "original_type": "transaction",
     *         "algorithm": "AEAD_AES_256_GCM",
     *         "ciphertext": "",
     *         "associated_data": "",
     *         "nonce": ""
     *     }
     *
     * @param body
     * @return
     */
    public String decryptBody(String body, String apiV3Key) throws UnsupportedEncodingException, GeneralSecurityException {

        AesUtil aesUtil = new AesUtil(apiV3Key.getBytes("utf-8"));

        JSONObject object = JSONObject.parseObject(body);
        JSONObject resource = object.getJSONObject("resource");
        String ciphertext = resource.getString("ciphertext");
        String associatedData = resource.getString("associated_data");
        String nonce = resource.getString("nonce");

        return aesUtil.decryptToString(associatedData.getBytes("utf-8"),nonce.getBytes("utf-8"),ciphertext);

    }

}
